﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

using VDataAdapter.EventManagement;
using VDataAdapter.TestPreparation;
using VDataAdapter.WorkerManagement;
using VDataAdapter.Communication;
using VDataAdapter.BlockingQueue;
using VDataAdapter.QueueManagement;
using VDataAdapter.ClientManagement;
using VDataAdapter.PriceServerAdapter;

using log4net;

namespace VDataAdapter.PriceServerAdapter
{
    /// <summary>
    /// This factory will create a PSHandler from file that load data and push into the worker queue in the correct order
    /// Send Top3PricesEvent after initial setup
    /// </summary>
    class PSEventHandlerFromFileFactory : IPSEventQueueEnqueuerFactory
    {
        private FirstTimeEvent _firstTimeEvent;
        private TransactionsEvent[] _transactionEvents;
        private Top3PricesEvent[] _top3PriceEvents;

        public PSEventHandlerFromFileFactory(FirstTimeEvent firstTimeEvent, TransactionsEvent[] transactionEvents, Top3PricesEvent[] top3PriceEvents)
        {
            _firstTimeEvent = firstTimeEvent;
            _transactionEvents = transactionEvents;
            _top3PriceEvents = top3PriceEvents;
        }
        public PSEventQueueEnqueuer createPSEventHandler(IEventStoteredQueue eventQueue, PSListenerExceptionHandler handler)
        {
            return new PSEventHandlerFromFile(handler, _firstTimeEvent, _transactionEvents, _top3PriceEvents, eventQueue);
        } 
    }

    /// <summary>
    /// This factory will create a PSHandler from file that load data and push into the worker queue in the correct order
    /// Send MarketInfosEvent after initial setup
    /// </summary>

    class PSMarketEventHandlerFromFileFactory : IPSEventQueueEnqueuerFactory
    {
        private FirstTimeEvent _firstTimeEvent;
        private TransactionsEvent[] _transactionEvents;
        private MarketInfosEvent[] _marketInfosEvents;

        public PSMarketEventHandlerFromFileFactory(FirstTimeEvent firstTimeEvent, TransactionsEvent[] transactionEvents, MarketInfosEvent[] marketInfosEvents)
        {
            _firstTimeEvent = firstTimeEvent;
            _transactionEvents = transactionEvents;
            _marketInfosEvents = marketInfosEvents;
        }
        public PSEventQueueEnqueuer createPSEventHandler(IEventStoteredQueue eventQueue, PSListenerExceptionHandler handler)
        {
            return new MarketInfoEnqueuer(handler, _firstTimeEvent, _transactionEvents, _marketInfosEvents, eventQueue);
        }
    }

    /// <summary>
    /// This PSHandler will load data from file and push into the worker queue in the correct order
    /// Send MarketInfosEvent after initial setup
    /// </summary>

    class MarketInfoEnqueuer : PSEventQueueEnqueuer
    {
        private FirstTimeEvent _firstTimeEvent;
        private TransactionsEvent[] _transactionEvents;
        private MarketInfosEvent[] _marketInfosEvents;

        public MarketInfoEnqueuer(PSListenerExceptionHandler handler, FirstTimeEvent firstTimeEvent, TransactionsEvent[] transactionEvents, MarketInfosEvent[] marketInfosEvents, IEventStoteredQueue eventQueue)
            : base(eventQueue, handler)
        { 
            _firstTimeEvent = firstTimeEvent;
            _transactionEvents = transactionEvents;
            _marketInfosEvents = marketInfosEvents;
        }

        public override void StartListening()
        {
            _eventQueue.PutFirstTimeEvent(_firstTimeEvent);

            foreach (TransactionsEvent te in _transactionEvents)
            {
                _eventQueue.PutTransactionsEvent(te);
            }

            foreach (MarketInfosEvent mke in _marketInfosEvents)
            {
                //Sleep a while
                Thread.Sleep(100);

                if (mke.MarketInfosList.ContainsKey(10))
                    Console.Write("test"); // for debugging

                //Put Stock event
                _eventQueue.PutMarketInfosEvent(mke);

                
            }

        }

        public override void StopListening()
        {
            throw new NotImplementedException();
        }
    }


    /// <summary>
    /// This PSHandler will load data from file and push into the worker queue in the correct order
    /// Send Top3PricesEvent after initial setup
    /// </summary>
    class PSEventHandlerFromFile : PSEventQueueEnqueuer
    {
        // protected IEventStoteredQueue _eventQueue;
        private FirstTimeEvent _firstTimeEvent;
        private TransactionsEvent[] _transactionEvents;
        private Top3PricesEvent[] _top3PriceEvents;

        public PSEventHandlerFromFile(PSListenerExceptionHandler handler, FirstTimeEvent firstTimeEvent, TransactionsEvent[] transactionEvents, Top3PricesEvent[] top3PriceEvents, IEventStoteredQueue eventQueue)
            : base(eventQueue, handler)
        {
            _eventQueue = eventQueue;
            _firstTimeEvent = firstTimeEvent;
            _transactionEvents = transactionEvents;
            _top3PriceEvents = top3PriceEvents;
        }

        public override void StartListening()
        {
            _eventQueue.PutFirstTimeEvent(_firstTimeEvent);

            foreach (TransactionsEvent te in _transactionEvents)
            {
                _eventQueue.PutTransactionsEvent(te);
            }

            foreach (Top3PricesEvent t3e in _top3PriceEvents)
            {
                //Sleep a while
                Thread.Sleep(100);

                //Put Stock event
                _eventQueue.PutTop3PricesEvent(t3e);
            }

        }

        public override void StopListening()
        {
            //Do nothing
        }
    }

    /// <summary>
    /// This factory will create a PSHandler from file that push into the worker queue in the correct order
    /// Send Top3PricesEvent after initial setup
    /// Throw an exception at the count of 300 Top3PriceEvent
    /// </summary>
    class PSEventHandlerFromFileWithExceptionFactory : IPSEventQueueEnqueuerFactory
    {
        private FirstTimeEvent _firstTimeEvent;
        private TransactionsEvent[] _transactionEvents;
        private Top3PricesEvent[] _top3PriceEvents;

        public PSEventHandlerFromFileWithExceptionFactory(FirstTimeEvent firstTimeEvent, TransactionsEvent[] transactionEvents, Top3PricesEvent[] top3PriceEvents)
        {
            _firstTimeEvent = firstTimeEvent;
            _transactionEvents = transactionEvents;
            _top3PriceEvents = top3PriceEvents;
        }
        public PSEventQueueEnqueuer createPSEventHandler(IEventStoteredQueue eventQueue, PSListenerExceptionHandler handler)
        {
            return new PSEventHandlerFromFileWithException(handler, _firstTimeEvent, _transactionEvents, _top3PriceEvents, eventQueue);
        }
    }

    /// <summary>
    /// This PSHandler will load data from file and push into the worker queue in the correct order
    /// Send Top3PricesEvent after initial setup
    /// Throw an exception at the count of 300 Top3PriceEvent
    /// </summary>

    class PSEventHandlerFromFileWithException : PSEventQueueEnqueuer
    {
        private IEventStoteredQueue _eventQueue;
        private FirstTimeEvent _firstTimeEvent;
        private TransactionsEvent[] _transactionEvents;
        private Top3PricesEvent[] _top3PriceEvents;

        public PSEventHandlerFromFileWithException(PSListenerExceptionHandler handler, FirstTimeEvent firstTimeEvent, TransactionsEvent[] transactionEvents, Top3PricesEvent[] top3PriceEvents, IEventStoteredQueue eventQueue)
            : base(eventQueue, handler)
        {
            _eventQueue = eventQueue;
            _firstTimeEvent = firstTimeEvent;
            _transactionEvents = transactionEvents;
            _top3PriceEvents = top3PriceEvents;
        }

        public override void StartListening()
        {
            _eventQueue.PutFirstTimeEvent(_firstTimeEvent);

            foreach (TransactionsEvent te in _transactionEvents)
            {
                _eventQueue.PutTransactionsEvent(te);
            }

            int count = 0;
            foreach (Top3PricesEvent t3e in _top3PriceEvents)
            {
                //Sleep a while
                Thread.Sleep(100);

                if (count > 300)
                {
                    _psListenerExceptionHandler(new Exception("Test Exception... Thrown at count 301"));
                    return;
                }
                //Put stock event
                _eventQueue.PutTop3PricesEvent(t3e);

                //Increase count
                count++;
            }

        }

        public override void StopListening()
        {
            //Do nothing
        }
    }

    /// <summary>
    /// This factory will create a PSHandler from file that push into the worker queue in the correct order
    /// Send Top3PricesEvent after initial setup
    /// Throw an exception at the count of 300 Top3PriceEvent
    /// </summary>
    class ManualEventHandlerFactory : IPSEventQueueEnqueuerFactory
    {
        public ManualEventHandlerFactory()
        {
            
        }
        public PSEventQueueEnqueuer createPSEventHandler(IEventStoteredQueue eventQueue, PSListenerExceptionHandler handler)
        {
            return new ManualEventHandler(handler, eventQueue);
        }
    }

    /// <summary>
    /// This PSHandler will load data from file and push into the worker queue in the correct order
    /// Send Top3PricesEvent after initial setup
    /// Throw an exception at the count of 300 Top3PriceEvent
    /// </summary>

    class ManualEventHandler : PSEventQueueEnqueuer
    {
        public ManualEventHandler(PSListenerExceptionHandler handler, IEventStoteredQueue eventQueue)
            : base(eventQueue, handler)
        {
        }

        public override void StartListening()
        {
            var inputEventForm = new InputEventForm(_eventQueue);
            Application.Run(inputEventForm);

        }

        public override void StopListening()
        {
            //Do nothing
        }
    }

    /// <summary>
    /// This factory will create a donothing PSHandler
    /// Which do nothing just stop after being called
    /// </summary>
    class DoNothingPSEventQueueEnqueuerFactory : IPSEventQueueEnqueuerFactory
    {
        public PSEventQueueEnqueuer createPSEventHandler(IEventStoteredQueue eventQueue, PSListenerExceptionHandler handler)
        {
            return new DoNothingPSEventQueueEnqueuer(eventQueue, handler);
        }
    }

    /// <summary>
    /// This PSHandler will do nothing just stop after being called
    /// </summary>
    class DoNothingPSEventQueueEnqueuer : PSEventQueueEnqueuer
    {
        public DoNothingPSEventQueueEnqueuer(IEventStoteredQueue eventQueue, PSListenerExceptionHandler handler)
            : base(eventQueue, handler)
        {

        }

        public override void StartListening()
        {
            //Do Nothing
        }

        public override void StopListening()
        {
            //Do Nothing
        }
    }
}